#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <cstdlib>
#include <sys/socket.h>
#include <cstring>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <functional>
const std::string IP = "0.0.0.0";
const int MAXBUFSIZE = 1024;
using func_t = std::function<std::string(const std::string&)>;
class server
{
public:
    server(uint16_t port, func_t handle, std::string ip = IP)
        :_port(port),_ip(ip)
    {
        running = false;
        _handle = handle;
        _sock_fd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sock_fd < 0)
        {
           std::cout<<"socket error"<<std::endl;
           exit(1);
        }

        sockaddr_in svr_addr;
        svr_addr.sin_family = AF_INET;
        svr_addr.sin_port = htons(_port);
        svr_addr.sin_addr.s_addr = inet_addr(_ip.c_str());
        socklen_t len = sizeof(svr_addr);
        int err = bind(_sock_fd, (sockaddr*)&svr_addr, len);
        if(err != 0)
        {
            std::cout<<"bind error"<<std::endl;
            exit(1);
        }

    }
    void run()
    {
        running = true;
        sockaddr_in client_addr;
        char buf[MAXBUFSIZE];
        std::cout << "Server running..." << std::endl;
        while(running)
        {
            memset(buf, 0, MAXBUFSIZE);
            socklen_t len = sizeof(client_addr);
            ssize_t recv_size = recvfrom(_sock_fd, buf, sizeof(buf) - 1,0,(sockaddr*)&client_addr, &len);
            client_addr.sin_port = ntohs(client_addr.sin_port);
            client_addr.sin_addr.s_addr = ntohl(client_addr.sin_addr.s_addr);
            if(recv_size < 0)
            {
                std::cout<<"recv error"<<std::endl;
                continue;
            }
            //处理数据
            std::string ret = _handle(std::string(buf));
            std::cout << ret << std::endl;

            memset(buf, 0, MAXBUFSIZE);

            ssize_t send_size = sendto(_sock_fd, ret.c_str(), ret.size(), 0, (sockaddr*)&client_addr, len);
            if(send_size < 0)
            {
                std::cout<<"send error"<<std::endl;
                continue;
            }

        }
    }
private:
    func_t _handle;
    int _sock_fd;
    bool running;
    uint16_t _port;
    std::string _ip;
};

